import cv2 as cv
import numpy as np


# Hough的原理y=kx+b或者ρ=xcosθ+ysinθ,有两种参数空间（k,b）和（ρ，θ）
# 标准霍夫线变换，该函数的功能是通过一组参数对（θ，r）的集合来表示检测到的直线
def line_detection(image, method='HoughLines'):
    img = image.copy()
    gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    edges = cv.Canny(gray, 50, 150, apertureSize=3)  # apertureSize参数默认其实就是3（canny边缘检测中梯度那一步中卷积核的大小）
    cv.imshow("edges", edges)
    if method == 'HoughLines':
        lines = cv.HoughLines(edges, 1, np.pi/180, 100)
        # image参数表示边缘检测的输出图像，该图像为单通道8位二进制图像。
        # rho参数表示参数极径r以像素值为单位的分辨率，这里一般使用1像素。
        # theta参数表示参数极角θ以弧度为单位的分辨率，这里使用1度。
        # threshold参数表示检测一条直线所需最少的曲线交点,该数值越大则所绘出的直线越少
        for line in lines:
            rho, theta = line[0]  # line[0]存储的是点到直线的极径和极角，其中极角是弧度表示的。
            a = np.cos(theta)  # theta是弧度
            b = np.sin(theta)
            x0 = a * rho  # 代表x = r * cos（theta）
            y0 = b * rho  # 代表y = r * sin（theta）
            x1 = int(x0 + 1000 * (-b))  # 计算直线起点横坐标
            y1 = int(y0 + 1000 * a)  # 计算起始起点纵坐标
            x2 = int(x0 - 1000 * (-b))  # 计算直线终点横坐标
            y2 = int(y0 - 1000 * a)  # 计算直线终点纵坐标    注：这里的数值1000给出了画出的线段长度范围大小，数值越小，画出的线段越短，数值越大，画出的线段越长
            cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 点的坐标必须是元组，不能是列表。
            # 第一个参数表示输入的图像，第二三个参数分别表示直线的起点和终点，第四个参数表示所绘直线的颜色，第五个参数表示所绘直线的颜色
    elif method == 'HoughLinesP':  # 统计概率霍夫线变换，该函数能输出检测到的直线的端点
        lines = cv.HoughLinesP(edges, 1, np.pi / 180, 60, minLineLength=60, maxLineGap=5)
        # image参数表示边缘检测的输出图像，该图像为单通道8位二进制图像。
        # rho参数表示参数极径θ以像素值为单位的分辨率，这里一般使用1像素。
        # theta参数表示参数极角r以弧度为单位的分辨率，这里使用1度。
        # threshold参数表示检测一条直线所需最少的曲线交点。
        # minLineLength参数表示能组成一条直线的最少点的数量，点数量不足的直线将被抛弃。
        # maxLineGap参数表示能被认为在一条直线上的亮点的最大距离。
        for line in lines:
            x1, y1, x2, y2 = line[0]
            cv.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
    else:
        raise BaseException("参数传入有误")
    cv.imshow("image_lines", img)


src = cv.imread('imgs/test008.jpg')
cv.imshow('input_image', src)
line_detection(src, method="HoughLinesP")
cv.waitKey(0)
cv.destroyAllWindows()
